//
// Created by huyi on 24-6-16.
//
#pragma once
#include "AmaInstance.h"
#include "DolphindbInstance.h"

#include <ama.h>

#include <folly/dynamic.h>
#include <folly/io/async/AsyncSignalHandler.h>
#include <folly/logging/xlog.h>
#include <folly/ProducerConsumerQueue.h>

#include <boost/program_options.hpp>

#if defined(_MSC_VER)
#define SIGUSR1 10
#define SIGUSR2 12
#endif

namespace tradev::app {

/*!
 * @brief
 */
class QuoteAmaLiteService {
public:
  using AmaInstancePtr        = std::unique_ptr<AmaInstance>;
  using DolphindbInstancePtr  = std::unique_ptr<DolphindbInstance>;
  using MdSnapshotAppenderPtr = std::unique_ptr<MdSnapshotAppender>;

  class SignalHandler : public folly::AsyncSignalHandler {
  public:
    SignalHandler(
      folly::EventBase*          eventBase,
      QuoteAmaLiteService*       service,
      std::initializer_list<int> signals)
        : AsyncSignalHandler(eventBase)
        , _service(service)
        , _signals(signals) {
      for (auto sig : signals) {
        this->registerSignalHandler(sig);
        XLOGF(INFO, "Register signal({}) handler", sig);
      }
    }

    void signalReceived(int signum) noexcept override;

    bool _called{false};

    std::vector<int>     _signals;
    QuoteAmaLiteService* _service;
  };

public:
  QuoteAmaLiteService(folly::EventBase* evb, folly::dynamic options, Args args);

  ~QuoteAmaLiteService() { close(); }

  int open();

  void close() noexcept;

  void run();

  MdSnapshotAppender* md_appender() { return _md_appender.get(); }
  DolphindbInstance*  dolphindb() { return _dolphindb.get(); }


  /*!
   * @brief 检查Dolphindb是否健康
   */
  FOLLY_NODISCARD
  bool checkDolphindbHealth() const {
    return _dolphindb && _dolphindb->isAvaliable();
  }

private:
  int createAma();

  int createDolphindb();

  void scheduleCheckAmaJob();

  void scheduleCheckDolphindbJob();

  void consumer();

  void consumerLoop();

  /*!
   * @brief 检查QuoteAmaLiteService的有效性
   * @return
   */
  FOLLY_NODISCARD
  bool isAvaliable() const {
    return !_closed && !_closing && _evb->isRunning();
  }

  std::atomic_bool _closed{true};
  std::atomic_bool _closing{false};

  Options _options;
  Args    _args;

  folly::EventBase*     _evb;
  AmaInstancePtr        _ama;
  DolphindbInstancePtr  _dolphindb;
  QueueType             _queue;
  MdSnapshotAppenderPtr _md_appender;
};

} // namespace tradev::app
